package cn.edu.tsinghua.ie.ieFunds.controller;

import cn.edu.tsinghua.ie.ieFunds.bean.base.Stock;
import cn.edu.tsinghua.ie.ieFunds.bean.bussiness.Fund;
import cn.edu.tsinghua.ie.ieFunds.bean.bussiness.FundStock;
import cn.edu.tsinghua.ie.ieFunds.bean.bussiness.Transaction;
import cn.edu.tsinghua.ie.ieFunds.bean.system.User;
import cn.edu.tsinghua.ie.ieFunds.service.*;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@RestController
@RequestMapping("fund")
public class FundController {

    @Autowired
    private StockService stockService;

    @Autowired
    private FundService fundService;

    @Autowired
    private TransactionService transactionService;

    @Autowired
    private FundStockService fundStockService;

    @Autowired
    private UserService userService;

    @RequestMapping(value = "getFund", method = RequestMethod.GET)
    public Fund getFund(String fundUid) {
        UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext()
                .getAuthentication()
                .getPrincipal();
        String username = userDetails.getUsername();
        Fund fund = fundService.getFundByFundUid(fundUid);
        if (fund.getUsername().compareTo(username) == 0) {
            return fund;
        }
        //TODO HttpResult
        else return null;
    }

    @RequestMapping(value = "getFundList", method = RequestMethod.GET)
    public List<Fund> getFundList() {
        UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext()
                .getAuthentication()
                .getPrincipal();
        String username = userDetails.getUsername();
        return fundService.findFundListByUsername(username);
    }

    @RequestMapping(value = "add", method = RequestMethod.POST)
    public void add(@RequestBody Fund fund, int[] quantity) {
        fund.setCreateDate(new Date());
        UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext()
                .getAuthentication()
                .getPrincipal();
        String username = userDetails.getUsername();
        User user = userService.getUserByUsername(username);
        fund.setUsername(username);

        List<FundStock> fundStockList = new ArrayList<>();
        List<Stock> stockList = stockService.getDistinctList();
        Date now = new Date();
        for (Stock stock : stockList) {
            int index = stockList.indexOf(stock);
            //if (quantity[index] <=0) continue;

            // generate fund stock
            FundStock fundStock = new FundStock();
            fundStock.setStock(stock);
            fundStock.setStockQuantity(quantity[stockList.indexOf(stock)]);
            fundStockService.save(fundStock);
            fundStockList.add(fundStock);

            // update stock
            stock.setRemainQuantity(stock.getRemainQuantity() - quantity[index]);

            // save transaction
            Transaction transaction = new Transaction();
            transaction.setPrice(stock.getPrice());
            transaction.setQuantity(quantity[index]);
            transaction.setStock(stock);
            transaction.setTime(now);
            transaction.setUser(user);
            transaction.setType(Transaction.TX_TYPE_BUY);
            transactionService.add(transaction);

            // update fund cash
            //FIXME if the cash is negative
            fund.setCash(fund.getCash() - stock.getPrice() * quantity[index]);
        }
        fund.setFundStocks(fundStockList);
        fundService.add(fund);
    }

    @RequestMapping(value = "modify", method = RequestMethod.POST)
    public void modify(String fundUid, int[] sellQuantity, int[] buyQuantity) {
        UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext()
                .getAuthentication()
                .getPrincipal();
        String username = userDetails.getUsername();
        User user = userService.getUserByUsername(username);

        Fund fund = fundService.getFundByFundUid(fundUid);

        List<FundStock> fundStockList = fund.getFundStocks();

        System.out.println(JSON.toJSONString(sellQuantity));
        System.out.println(JSON.toJSONString(buyQuantity));
        //List<Stock> stockList = stockService.getDistinctList();
        Date now = new Date();

        for (FundStock fundStock : fundStockList) {
            int index = fundStockList.indexOf(fundStock);
            Stock stock = fundStock.getStock();

            // update fund stock
            if (fundStock.getStockQuantity() - sellQuantity[index] + buyQuantity[index] > 0) {
                fundStock.setStockQuantity(fundStock.getStockQuantity() - sellQuantity[index] + buyQuantity[index]);
            }

            // update stock
            stock.setRemainQuantity(stock.getRemainQuantity() + sellQuantity[index] - buyQuantity[index]);
            stockService.save(stock);

            // save transaction
            if (sellQuantity[index] > 0) {
                Transaction transaction = new Transaction();
                transaction.setPrice(stock.getPrice());
                transaction.setQuantity(sellQuantity[index]);
                transaction.setStock(stock);
                transaction.setTime(now);
                transaction.setUser(user);
                transaction.setType(Transaction.TX_TYPE_SELL);
                transactionService.add(transaction);
            }
            if (buyQuantity[index] > 0) {
                Transaction transaction = new Transaction();
                transaction.setPrice(stock.getPrice());
                transaction.setQuantity(buyQuantity[index]);
                transaction.setStock(stock);
                transaction.setTime(now);
                transaction.setUser(user);
                transaction.setType(Transaction.TX_TYPE_BUY);
                transactionService.add(transaction);
            }

            // update fund cash
            //FIXME if the cash is negative
            fund.setCash(fund.getCash() - fundStock.getStock().getPrice() * buyQuantity[index] + fundStock.getStock().getPrice() * sellQuantity[index]);
        }
        fundService.add(fund);
    }
}
